/**
 * 类名：XKCollecter
 * @author hmb
 * 创建日期： 2014-10-1 上午1:00:04
 * 
 */
package com.erms.domain;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.jsoup.nodes.Document;

import com.erms.Config;
import com.erms.bean.Department;
import com.erms.bean.Major;
import com.erms.bean.StudentTeach;
import com.erms.bean.StudentTeachId;
import com.erms.bean.Teach;
import com.erms.bean.User;
import com.erms.domain.handler.DepartmentPaserHandler;
import com.erms.domain.handler.MajorPaserHandler;
import com.erms.domain.handler.SchedulePaserHandler;
import com.erms.util.HtmlParser;
import com.erms.util.HttpUtil;
import com.erms.util.LogUtil;
import com.erms.util.http.HttpRequest;
import com.erms.util.http.HttpResult;
import com.erms.util.http.XmlParserHandler;

/**
 * @author hmb
 * 
 *         备注：用于对南理工选课网站进行远程抓取数据的封装类。
 *         抓取的数据包括：所有课程信息数据；必、选修课信息；本学期课表等，
 *         考虑是否加入成绩信息抓取
 */
public class XKCollecter {

	public static final String	DOMAIN_XUANKE				= "http://202.119.81.118:7777";

	// post表单
	// 参数：stuid
	// 学号、
	// pwd密码
	public static final String	URL_XUANKE_LOGIN			= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.login";
	public static final String	URL_XUANKE_TONGZHI			= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.xktz";
	public static final String	URL_XUANKE_BIXIUKE			= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.CourseInput_bxk";
	public static final String	URL_XUANKE_RENXUANKE		= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.CourseInput_rxk";
	public static final String	URL_XUANKE_KEBIAO			= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.CourseView";
	public static final String	URL_XUANKE_ZHUANYE			= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.kccx_zy";
	public static final String	URL_XUANKE_YUANXI			= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.kccx_yx";
	public static final String	URL_XUANKE_XINXI			= DOMAIN_XUANKE
																	+ "/pls/wwwxk/xk.loginmessage";
	// post表单
	// 参数:
	// v_nj选择年级、
	public static final String	URL_XUANKE_CHAXUN_FORM		= DOMAIN_XUANKE
																	+ "xk.kccx_zy_submit";
	// v_xsh_zyh选择院系、专业，详情查看课程查询网站
	public static final String	URL_XUANKE_CHAXUN_RESULT	= DOMAIN_XUANKE
																	+ "/xk/kccx/kccx_bottom1.htm";
	// 教务处各网页均是gbk编码
	private static final String	GBK							= "GBK";

	private HttpResult			result						= null;

	private String				id							= null;
	private String				password					= null;

	private Logger				logger						= null;

	public HttpResult getResult() {

		return result;
	}

	public void setResult(HttpResult result) {

		this.result = result;
	}

	/**
	 * 构造函数，用学号和密码来初始化
	 * 
	 * @param id
	 *            学号
	 * @param password
	 *            密码
	 */
	public XKCollecter(String id, String password) {

		this.id = id;
		this.password = password;
		logger = LogUtil.getLogger(getClass());
	}

	/**
	 * 登录到选课系统，由执行具体任务（比如查询课表）时会先自动调用此函数，也可以手动调用达到判断学号密码
	 * 
	 * @return true 登录成功 或 false 登录失败
	 */
	public boolean login() {

		HttpRequest requst = new HttpRequest();
		// 下面两个键是选课系统登录表单的参数名，且认为它是不变的
		requst.setParam("stuid", id).setParam("pwd", password);
		result = HttpUtil.post(URL_XUANKE_LOGIN, requst, GBK);
		// "你输入了错误的学号或密码，不能登录！"当选课系统登录失败时反馈这句话，以此来判断是否登录成功
		if (result != null && !result.getContent().contains("输入了错误的学号或密码")) { return true; }
		return false;
	}

	public User getUserInfo() {

		// 重新登录，避免登录过期
		if (!login()) {
			logger.debug("登录失败");
			return null;
		}
		String cookie = result.getCookie();
		HttpRequest request = new HttpRequest();
		request.setCookies(cookie);
		result = HttpUtil.get(URL_XUANKE_XINXI, request, GBK);

		HtmlParser parser = new HtmlParser();
		return parser.parse(result.getContent(), new XmlParserHandler<User>() {

			@Override
			public List<User> onParse(Document document) {
				List<User> list = new ArrayList<>();
				User user = null;
				String userInfo = document.select("h4").text();
				logger.debug("抓取到的用户信息字段: "+ userInfo);
				if (userInfo.contains("姓名")) {
					String[] infos = userInfo.replace("(", ",").replace(")", "").replace('，', ',').replace('：', ':').replace(' ', ',').split(",");
					logger.debug("拆分后的字段数组长度："+infos.length);
					if (infos.length>= 6) {
						user = new User();
						user.setName(infos[0].split(":")[1]);
						user.setSex(infos[1]);
						user.setId(id);
						user.setPassword(password);
						user.setClassNum(infos[3].split(":")[1]);
						user.setDepartment(new Department(null, infos[4]));
						user.setMajor(new Major(null, null, infos[5]));
					}
				}
				// 姓名：黄名堡(男)，学号：912106840218，班级：9121065501(计算机科学与技术学院
				// 软件工程专业,专业方向：方向一)
				list.add(user);
				return list;
			}

			@Override
			public void onError() {

				// TODO 自动生成的方法存根

			}
		}).get(0);
	}

	/**
	 * 取得课程表，不为空，若找不到课表则列表长度为0<br>
	 * 教师信息仅包括姓名
	 * 
	 * @return 永不为空，如果未能正确取得则长度为0
	 */
	public List<StudentTeach> getSchedule() {

		// 重新登录，避免登录过期
		if (!login()) {
			logger.debug("登录失败");
			return new ArrayList<>();
		}
		String cookie = result.getCookie();
		HttpRequest request = new HttpRequest();
		request.setCookies(cookie);
		result = HttpUtil.get(URL_XUANKE_KEBIAO, request, GBK);

		HtmlParser parser = new HtmlParser();
		SchedulePaserHandler schedulePaserHandler = new SchedulePaserHandler(
				this.id, this.password);
		return parser.parse(result.getContent(), schedulePaserHandler);

	}

	/**
	 * 取得教务处网站上的专业信息，过滤了部分非本校学院的专业.<br>
	 * 注意:专业信息依赖于学院信息，持久化专业信息前请确保数据库中存在对应的学院信息
	 * 
	 * @return 永不为空，如果未能正确取得专业信息则长度为0
	 */
	public List<Major> getMajors() {

		if (!login()) {
			logger.debug("登录失败");
			return new ArrayList<>();
		}
		HttpRequest request = new HttpRequest();
		request.setCookies(result.getCookie());
		result = HttpUtil.get(URL_XUANKE_ZHUANYE, request, GBK);

		HtmlParser parser = new HtmlParser();
		MajorPaserHandler handler = new MajorPaserHandler();
		return parser.parse(result.getContent(), handler);
	}

	/**
	 * 取得教务网站上的学院（部门）信息，过滤了部分过期编号的学院（部门）
	 * 
	 * @return 永不为空，如果未能正确取得学院信息则长度为0
	 */
	public List<Department> getDepartments() {

		if (!login()) {
			logger.debug("登录失败");
			return new ArrayList<>();
		}
		HttpRequest request = new HttpRequest();
		request.setCookies(result.getCookie());
		result = HttpUtil.get(URL_XUANKE_YUANXI, request, GBK);

		HtmlParser parser = new HtmlParser();
		DepartmentPaserHandler handler = new DepartmentPaserHandler();
		return parser.parse(result.getContent(), handler);
	}

	// 这只是个测试方法
	public static void main(String[] args) {

		//
		// HttpRequest requst = new HttpRequest();
		// requst.addParam("stuid", "912106840218");
		// requst.addParam("pwd", "413516");
		// result = HttpUtil.post(URL_XUANKE_LOGIN, requst, GBK);

		// XmlParser parser = new XmlParser();
		// parser.save("d:\\kebiao.xml", result.getContent());
		// parser.parseHTML(result.getContent());

		// HtmlParser parser = new HtmlParser();
		// 此文件是课表页面的缓存，用上面的注释代码生成
		// parser.parseFromFile("d:\\kebiao.xml", schedulePaserHandler);
		XKCollecter collecter = new XKCollecter(Config.STUDENT_ID,
				Config.STUDENT_PASSWORD);
		List<StudentTeach> scheduleList = collecter.getSchedule();
		int n = scheduleList.size();
		LogUtil.debug("总课数：" + n);
		if (n != 0) {
			User student = scheduleList.get(0).getId().getUser();
			LogUtil.debug("学生：" + student.toString());
			LogUtil.debug(student.getClassNum());
			LogUtil.debug(student.getDepartment().getName());
			LogUtil.debug(student.getMajor().getName());
		}
		for (int i = 0; i < n; i++) {
			StudentTeachId key = scheduleList.get(i).getId();
			Teach teach = key.getTeach();
			LogUtil.debug("星期" + teach.getDayOfWeek());
			LogUtil.debug("第" + teach.getSectionOfDay() + "大节");
			LogUtil.debug(teach.getId());
			LogUtil.debug(teach.getTeacherName());
			LogUtil.debug(teach.getCourse().getId());
			LogUtil.debug(teach.getSeq());
			LogUtil.debug(teach.getCourse().getName());
			LogUtil.debug(teach.getAddress());
			LogUtil.debug(teach.getWeek());

		}
	}

}
